#include <iostream>
#include <functional>
using namespace std;

using namespace placeholders;

class statefun {
public:
	static void hello(int i) {
		cout << "statefun::hello i=" << i << endl;
	}
};
class Hello {
public:
	void operator()(int count) {
		cout << "Hello::operator() i=" << count << endl;
	}
	void operator()(int a, int b) {
		cout << "Hello operator(int,int) a b= " << a << b << endl;
	}
};
class CHello {
public:
	void hello(int count) {
		cout << "CHello hello count=" << count << endl;
	}
};
int i = 1;
void hello(int count) {
	count++;
	cout << "void hello count=" << count << endl;
}
class LambdaHello {
public:
	LambdaHello(int _i) :i(_i) {
		cout << "LambdaHello cout i= " << i << endl;
	}
	void operator()(int count) {
		cout << "LambdaHello operator() cout i=" << i << endl;
	}
private:
	int i;
};


int main() {

	function<void(int)> f_hello1 = hello;
	f_hello1(i);//void hello count=2

	function<void(int)> f_hello2 = &hello;
	f_hello2(i);//void hello count=2

	function<void(int)> f_hello3 = &statefun::hello;
	f_hello3(3);//statefun::hello i=3

	function<void(int)> f_hello4 = Hello();
	f_hello4(4);//Hello::operator() i=4

	function<void(int, int)> f_hello5 = Hello();
	f_hello5(5, 15);//Hello operator(int,int) a b= 515

	function<void(CHello*, int)> f_hello6 = &CHello::hello;
	CHello c;
	f_hello6(&c, 6);//CHello hello count=6


	//lambda
	//[]ֵ����()���ò���
	//ֵ�������޸��ⲿ����i��mutable�����޸��ⲿ����
	int val = 0;
	function<void(int)> f_hello7 = [val](int count)mutable->void {
		val++;
		cout << "lambda cout = " << val << endl;
	};
	f_hello7(12);//lambda cout = 1
	cout << "val cout :" << val << endl;//val cout :0

	function <void(int)> f_hello8 = LambdaHello(i);
	f_hello8(13);//LambdaHello cout i= 1
	//LambdaHello operator() cout i=1

//bind
	function<void()> f_hello9 = bind(&hello, 9);
	f_hello9();//void hello count=10

	function <void()> f_hello10 = bind(&CHello::hello, &c, 100);
	f_hello10();//CHello hello count=100

	function<void(int)> f_hello11 = bind(&CHello::hello, &c, placeholders::_1);
	f_hello11(121);//CHello hello count=121
	return 1;
//testval lalala
}